/*
1.從引用的專案說起 （或者是包本身新版0.80含以上）版本
引用的專案宣告一個新的 Configuration class
宣告一個bean ,
*/
 @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

/*
2.藉由serverEndpointExporter class  bean 初始化之後 實作SmartInitializingSingleton 注入其他 所需要的物件方法等等
*/   
public class ServerEndpointExporter extends ApplicationObjectSupport implements SmartInitializingSingleton{
	...
}

/*
3.在SmartInitializingSingleton中只有一個介面afterSingletonsInstantiated()，
其作用是是 在spring容器管理的所有單例物件（非懶載入物件）初始化完成之後呼叫的回撥介面
在 該 function 裡面 執行 registerEndpoints()
*/

/*

4.registerEndpoints function 主要是 對 有ServerEndpoint助解的類 進行動作
  4.1 先取得 ApplicationContext 	 context (AnnotationConfigEmbeddedWebApplicationContext)
  4.2 從context 取得 所有有寫 ServerEndpoint 這個compoment 類 所有宣告的 beanName 並取的類加入到 endpointClasses set
  4.3 call registerEndpoint function for all class in endpointClasses list
*/
  protected void registerEndpoints() {
        Set<Class<?>> endpointClasses = new LinkedHashSet<>();
        //ApplicationObjectSupport
        ApplicationContext context = getApplicationContext();
        if (context != null) {
        	//ServerEndpoint get server config bean
            String[] endpointBeanNames = context.getBeanNamesForAnnotation(ServerEndpoint.class);
            for (String beanName : endpointBeanNames) {
                endpointClasses.add(context.getType(beanName));
            }
        }

        for (Class<?> endpointClass : endpointClasses) {
            registerEndpoint(endpointClass);
        }

        init();
    }

/*
	5. registerEndpoint function define
	5.1 取的 有註解ServerEndpoint class 上面設定的註解值
	5.2 建立 ServerEndpointConfig class 並呼叫buildConfig function 將5.2上面的值寫入到config,
	同時將 application.yml上面有設定得值寫入 ServerEndpointConfig
	5.3建立 PojoMethodMapping class

*/
	 private void registerEndpoint(Class<?> endpointClass){
	 	   ServerEndpoint annotation = AnnotatedElementUtils.findMergedAnnotation(endpointClass, ServerEndpoint.class);
        if (annotation == null) {
            throw new IllegalStateException("missingAnnotation ServerEndpoint");
        }
        ServerEndpointConfig serverEndpointConfig = buildConfig(annotation);

        ApplicationContext context = getApplicationContext();
        PojoMethodMapping pojoMethodMapping = null;
        try {
        	//5.3 ,5.4
            pojoMethodMapping = new PojoMethodMapping(endpointClass, context);
        } catch (DeploymentException e) {
            throw new IllegalStateException("Failed to register ServerEndpointConfig: " + serverEndpointConfig, e);
        }

        InetSocketAddress inetSocketAddress = new InetSocketAddress(serverEndpointConfig.getHost(), serverEndpointConfig.getPort());
        WebsocketServer webSocketServer = addressWebsocketServerMap.get(inetSocketAddress);
        if (webSocketServer == null) {
        	//目前追蹤結果跑到這
            PojoEndpointServer pojoEndpointServer = new PojoEndpointServer(pojoMethodMapping, serverEndpointConfig);
            webSocketServer = new WebsocketServer(pojoEndpointServer, serverEndpointConfig);
            addressWebsocketServerMap.put(inetSocketAddress, webSocketServer);

        } else {
            String path = annotation.value();
            String prefix = annotation.prefix();
            if (!StringUtils.isEmpty(prefix)) {
                String pathFromEnv = environment.getProperty(prefix + ".path", String.class);
                if (pathFromEnv != null) {
                    path = pathFromEnv;
                }
            }
            webSocketServer.getPojoEndpointServer().addPathPojoMethodMapping(path, pojoMethodMapping);
        }

	 }
/*
	PojoMethodMapping class 定义了 webSocket 所需要的 Method instance 由传入的 endpointClass裡面有加上该注解的方法对应(@onOpen @onClose ...) 
	5.3 PojoMethodMapping class constructor 传入了 有加上@serverEndpoint注解的 class (上面包含加上注解的方法),跟 ApplicationContext
	5.4 in constructor,比对 各个注解定义类(OnOpen,OnClose...)取得 在 @ServerEndpoint 类裡面有加上该注解的方法,设定于 Method open,Method close,...
	5.5目前追蹤到 WebSocketServer 第一次初始化时传入 host 跟 port 回传null
	5.6重新new 一个 WebsocketServer ,先new 一个 PojoEndpointServer 将PojoMethodMapping and serverEndpointConfig 传入
	5.7在PojoEndpointServer中 宣告了 实际上 netty  server webSocket 方法的 实作,doOpen doColose等等...并在此实际呼叫 
	自己在业务中定义在@serverEndpoint注解的 class上的 onClose等等方法..
	(初始话时：传入于PojoMethodMapping -> PojoEndpointServer -->WebSocketServer)
	5.8 将初始化完成的WebSocketServer 放到自身宣告的 HashMap addressWebsocketServerMap, key is inetSocketAddress
	5.9 将所有有加上注解@ServerEndpoint的类重复初始化完后 ,回到 ServerEndpointExporter 呼叫 init function 
	5.10 init function : 呼叫 放在addressWebsocketServerMap 的 webSocketServer init 
	(主要是 ServerBootstrap 在设定 childHandler 时 new 一个 自定义包装 HttpServerHandler将 pojoEndpointServer 
	以及 serverEndpointConfig 传进去)
*/
